package domain.searchEngine ;

import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import junit.framework.Assert ;
import junit.framework.TestCase ;
import persistence.PersistenceController ;
import persistence.PersistenceFactory ;
import persistence.hibernate.HibernatePersistenceFactory ;
import persistence.xstream.XStreamPersistenceFactory ;
import persistence.xstream.XmlDatabaseFileList ;
import presentation.UIThread ;
import presentation.UIUser ;
import util.DateTools;
import util.NotFoundException ;
import util.Statistics ;
import domain.ForumData ;
import domain.message.MessageController ;
import domain.user.BadPasswordException ;
import domain.user.UnpermittedActionException ;
import domain.user.UserController ;

/**
 * @author idan
 */
public abstract class SearchEngineTest extends TestCase
{

	protected ForumData forum ;
	protected SearchEngineFactory searchProvider ;
	private MessageController messageController ;
	private UserController userController ;

	public SearchEngineTest()
	{
		super() ;
	}

	public SearchEngineTest(final String name)
	{
		super(name) ;
	}

	/**
	 * Test method for {@link domain.searchEngine.SearchEngine#getPostStatistics()}.
	 */
	public void testPostStatistics() throws UnpermittedActionException, NotFoundException
	{
		SearchEngine search = this.getSearchEngine() ;

		long adminId = this.forum.getAdmin().getId() ;
		UIThread t = this.messageController.addThread(this.forum.getRoot().getId(), adminId, "test", "post1") ;
		this.messageController.addPost(t.getId(), adminId, "post2") ;
		Statistics s = search.getPostStatistics() ;
		int sum = 0 ;
		for (int i = 0 ; i < s.getQuantum() ; i++)
		{
			sum += s.get(i) ;
		}
		Assert.assertEquals(2, sum) ;

		search.close() ;
	}

	/**
	 * Test method for {@link domain.searchEngine.SearchEngine#searchByAuthor(java.lang.String)}.
	 */
	
	public void testSearchByAuthor() throws UnpermittedActionException, NotFoundException
	{
		SearchEngine search = this.getSearchEngine() ;
		Set<SearchResult> ans = new HashSet<SearchResult>();
		long adminId = this.forum.getAdmin().getId() ;
		UIThread t = this.messageController.addThread(this.forum.getRoot().getId(), adminId, "subject test thread", "post message1") ;
		this.messageController.addPost(t.getId(), adminId, "post message2") ;
		ans = search.searchByAuthor(this.forum.getAdmin().getUsername());
		Assert.assertEquals(2, ans.size());
	}


	/**
	 * Test method for {@link domain.searchEngine.SearchEngine#searchByContent(java.lang.String)}.
	 */
	public void testSearchByContent() throws UnpermittedActionException, NotFoundException
	{
		SearchEngine search = this.getSearchEngine() ;
		Set<SearchResult> ans = new HashSet<SearchResult>();
		long adminId = this.forum.getAdmin().getId() ;
		
		UIThread t = this.messageController.addThread(this.forum.getRoot().getId(), adminId, "subject test thread", "post message1") ;
		this.messageController.addPost(t.getId(), adminId, "post message2") ;
		ans = search.searchByContent("post message2");
		Assert.assertEquals(1, ans.size());
	}

	/**
	 * Test method for {@link domain.searchEngine.SearchEngine#searchByDate(java.util.Date, java.util.Date)}.
	 */
	public void testSearchByDate() throws UnpermittedActionException, NotFoundException
	{
		SearchEngine search = this.getSearchEngine() ;
		Set<SearchResult> ans = new HashSet<SearchResult>();
		long adminId = this.forum.getAdmin().getId() ;
		
		UIThread t = this.messageController.addThread(this.forum.getRoot().getId(), adminId, "subject test thread", "post message1") ;
		this.messageController.addPost(t.getId(), adminId, "post message2") ;
		Date now = Calendar.getInstance().getTime() ;
		Date yesterday = DateTools.add(now, Calendar.DATE, -1) ;
		ans = search.searchByDate(yesterday, now);
		Assert.assertEquals(2, ans.size());
	}


	/**
	 * Test method for {@link domain.searchEngine.SearchEngine#getPostStatisticsForMember(long)}.
	 */
	public void testsPostStatisticsForMember() throws UnpermittedActionException, NotFoundException
	{
		SearchEngine search = this.getSearchEngine() ;

		long adminId = this.forum.getAdmin().getId() ;
		UIThread t = this.messageController.addThread(this.forum.getRoot().getId(), adminId, "test", "post1") ;
		this.messageController.addPost(t.getId(), adminId, "post2") ;
		Statistics s = search.getPostStatisticsForMember(adminId) ;
		int sum = 0 ;
		for (int i = 0 ; i < s.getQuantum() ; i++)
		{
			sum += s.get(i) ;
		}
		Assert.assertEquals(2, sum) ;

		search.close() ;
	}

	/**
	 * Test method for {@link domain.searchEngine.SearchEngine#getUserStatistics()}.
	 */
	public void testUserStatistics() throws NotFoundException, BadPasswordException, UnpermittedActionException
	{
		SearchEngine search = this.getSearchEngine() ;

		UIUser u = this.userController.login("admin", "12") ;
		this.userController.logout(u.getId()) ;
		u = this.userController.login("admin", "12") ;
		this.userController.logout(u.getId()) ;

		Statistics s = search.getUserStatistics() ;
		int sum = 0 ;
		for (int i = 0 ; i < s.getQuantum() ; i++)
		{
			sum += s.get(i) ;
		}
		Assert.assertEquals(2, sum) ;

		search.close() ;
	}

	protected HibernatePersistenceFactory getHibernatePersistence()
	{
		return new HibernatePersistenceFactory(PersistenceController.BUILD_NEW) ;
	}

	protected abstract PersistenceFactory getPersistenceProvider() ;

	protected abstract SearchEngineFactory getSearchProvider() ;

	protected XStreamPersistenceFactory getXStreamPersistence()
	{
		XmlDatabaseFileList list = this.getFileList() ;
		XStreamPersistenceFactory builder = new XStreamPersistenceFactory(PersistenceController.BUILD_NEW, list) ;
		return builder ;
	}

	@Override
	protected void setUp() throws Exception
	{
		super.setUp() ;
		PersistenceFactory builder = this.getPersistenceProvider() ;
		this.forum = new ForumData(builder);
		this.searchProvider = this.getSearchProvider() ;
		this.userController = new UserController(this.forum, this.searchProvider.getIndexAgent()) ;
		this.messageController = new MessageController(this.forum, this.searchProvider.getIndexAgent()) ;
	}

	@Override
	protected void tearDown() throws Exception
	{
		this.messageController.exit() ;
		this.userController.exit() ;
		super.tearDown() ;
	}

	private XmlDatabaseFileList getFileList()
	{
		XmlDatabaseFileList list = new XmlDatabaseFileList() ;
		list.setMemberFile("users.xml") ;
		list.setDirectoryFile("dirs.xml") ;
		list.setThreadFile("threads.xml") ;
		list.setPostFile("posts.xml") ;
		list.setLoginFile("logins.xml") ;
		return list ;
	}

	private SearchEngine getSearchEngine()
	{
		return this.searchProvider.getSearchEngine() ;
	}
}
